#include "stdafx.h"
#include "EnvMgr.h"
#include "Environment.h"
#include "Signals/EnvSigSource.h"
#include "../ConstStr/ConstStr.h"

using namespace Base::Env;

EnvMgr::EnvMgr()
    : m_activeEnv(0)
{
}

EnvMgr::~EnvMgr()
{
    for (Environments::iterator it = m_environments.begin();
         it != m_environments.end(); ++it)
    {
        delete it->second;
        it->second = 0;
    }

    m_environments.clear();
}

EnvMgr*
EnvMgr::get()
{
    static EnvMgr theInstance;
    return &theInstance;
}

void
EnvMgr::activeEnv(const void* envId, const bool force)
{
    Environments::const_iterator it = m_environments.find(envId);
    if (it != m_environments.end())
    {
        Environment* oldActiveEnv = m_activeEnv;
        Environment* newActiveEnv = it->second;

        if (   oldActiveEnv != newActiveEnv
            || force)
        {
            if (oldActiveEnv)
                oldActiveEnv->state(Environment::eNormal);

            m_activeEnv = newActiveEnv;

            if (newActiveEnv)
                newActiveEnv->state(Environment::eActive);

            // Send out a signal.
            EnvSigSource::get()->switchEnv(oldActiveEnv, newActiveEnv);
        }
        else
            assert(false);
    }
}

void
EnvMgr::activeEnv(const void* envId)
{
    activeEnv(envId, false);
}

Environment*
EnvMgr::activeEnv() const
{
    return m_activeEnv;
}

void
EnvMgr::addEnv(const std::string& name,
               const std::wstring& title)
{
    const void* envId = Base::ConstStr::ConstStr::get()->string(name);
    Environments::const_iterator it = m_environments.find(envId);
    if (it != m_environments.end())
    {
        // Error: Duplicated type ID.
        assert(false);
        return;
    }

    Environment* env = new Environment(envId, title);
    m_environments[envId] = env;
}

void
EnvMgr::removeEnv(const std::string& name)
{
    removeEnv(Base::ConstStr::ConstStr::get()->string(name));
}

void
EnvMgr::removeEnv(const void* envId)
{
    Environments::iterator it = m_environments.find(envId);
    if (it != m_environments.end())
    {
        // Check if the environment to be delete just is the active one.
        // If so, deactivate it and assign it with null.
        if (m_activeEnv == it->second)
        {
            Environment* oldActiveEnv = m_activeEnv;
            m_activeEnv->onDeactivate();
            m_activeEnv = 0;
            EnvSigSource::get()->switchEnv(oldActiveEnv, m_activeEnv);
        }

        // Delete the environemnt.
        delete it->second;
        it->second = 0;

        // Remove the item.
        m_environments.erase(it);
    }
}

void
EnvMgr::reactivateEnv()
{
    if (m_activeEnv)
        activeEnv(m_activeEnv->id(), true);
}